package de.mmis.core.publishsubscribe;

import java.util.LinkedList;

import de.mmis.core.base.abstracttree.Tree;
import de.mmis.core.publishsubscribe.filter.Filter;

/**
 * internal class, being public only for deserialization.
 * 
 * @author Martin Nyolt
 * 
 */
public class Message {

	public static enum MessageType {
		EVENT, SUBSCRIBE, UNSUBSCRIBE, STATE_REQUEST, STATE_ANSWER
	}

	public Message() {
		// do nothing
	}

	static Message createEvent(PlainEvent e) {
		return createEvent(e, true);
	}

	static Message createEvent(PlainEvent e, boolean deliver) {
		Message result = new Message();
		result.type = MessageType.EVENT;
		result.event = e;
		result.deliver = deliver;
		return result;
	}

	static Message createSubscribe(Filter filter, String clazz, Integer id) {
		Message result = new Message();
		result.type = MessageType.SUBSCRIBE;
		result.filter = filter;
		result.clazz = clazz;
		result.id = id;
		return result;
	}

	static Message createUnsubscribe(LinkedList<Integer> ids) {
		Message result = new Message();
		result.type = MessageType.UNSUBSCRIBE;
		result.ids = ids;
		return result;
	}

	static Message createStateRequest(String id, String key, String destIP) {
		Message result = new Message();
		result.type = MessageType.STATE_REQUEST;
		result.deviceID = id;
		result.key = key;
		result.destIP = destIP;
		return result;
	}

	static Message createStateAnswer(String id, String key, Tree value,
			String destIP) {
		Message result = new Message();
		result.type = MessageType.STATE_ANSWER;
		result.deviceID = id;
		result.key = key;
		result.value = value;
		result.destIP = destIP;
		return result;
	}

	private MessageType type;
	private PlainEvent event;
	/**
	 * if this event should be delivered to a consumer - used to only update the
	 * worldstate
	 */
	private boolean deliver;
	private Filter filter;
	private String clazz;
	private Integer id;
	private LinkedList<Integer> ids;
	private String deviceID;
	private String key;
	private Tree value;
	private String destIP;

	@Override
	public String toString() {
		String result = type + " ";

		switch (type) {
		case EVENT:
			result += event + " -- ";
			result += "deliver: " + deliver;
			break;
		case STATE_ANSWER:
			result += "Device: " + deviceID + " ";
			result += "Key: " + key + " ";
			result += "Value: " + value + " ";
			result += "destIP: " + destIP;
			break;
		case STATE_REQUEST:
			result += "Device: " + deviceID + " ";
			result += "Key: " + key + " ";
			result += "destIP: " + destIP;
			break;
		case SUBSCRIBE:
			result += "Class: " + clazz + " ";
			result += "ID: " + id + " ";
			result += "Filter: " + filter;
			break;
		case UNSUBSCRIBE:
			result += "IDs: " + ids;
		}

		return result;
	}

	/**
	 * @param event
	 *            the event to set
	 */
	public void setEvent(PlainEvent event) {
		this.event = event;
	}

	/**
	 * @return the event
	 */
	public PlainEvent getEvent() {
		return event;
	}

	/**
	 * @param deliver
	 *            the deliver to set
	 */
	public void setDeliver(boolean deliver) {
		this.deliver = deliver;
	}

	/**
	 * @return the deliver
	 */
	public boolean getDeliver() {
		return deliver;
	}

	/**
	 * @param type
	 *            the type to set
	 */
	public void setType(MessageType type) {
		this.type = type;
	}

	/**
	 * @return the type
	 */
	public MessageType getType() {
		return type;
	}

	/**
	 * @param filter
	 *            the filter to set
	 */
	public void setFilter(Filter filter) {
		this.filter = filter;
	}

	/**
	 * @return the filter
	 */
	public Filter getFilter() {
		return filter;
	}

	/**
	 * @param clazz
	 *            the clazz to set
	 */
	public void setClazz(String clazz) {
		this.clazz = clazz;
	}

	/**
	 * @return the clazz
	 */
	public String getClazz() {
		return clazz;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}

	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}

	/**
	 * @param ids
	 *            the ids to set
	 */
	public void setIds(LinkedList<Integer> ids) {
		this.ids = ids;
	}

	/**
	 * @return the ids
	 */
	public LinkedList<Integer> getIds() {
		return ids;
	}

	/**
	 * @return the deviceID
	 */
	public String getDeviceID() {
		return deviceID;
	}

	/**
	 * @param deviceID
	 *            the deviceID to set
	 */
	public void setDeviceID(String deviceID) {
		this.deviceID = deviceID;
	}

	/**
	 * @return the key
	 */
	public String getKey() {
		return key;
	}

	/**
	 * @param key
	 *            the key to set
	 */
	public void setKey(String key) {
		this.key = key;
	}

	public Tree getValue() {
		return value;
	}

	public void setValue(Tree value) {
		this.value = value;
	}

	/**
	 * @param destIP
	 *            the destIP to set
	 */
	public void setDestIP(String destIP) {
		this.destIP = destIP;
	}

	/**
	 * @return the destIP
	 */
	public String getDestIP() {
		return destIP;
	}
}